// DOM-diff 对给定任意的两棵树，可以采用深度优先遍历的算法找到最少的转换步骤
// 根据 两个虚拟dom，找出差异，创建补丁

define(function() {
    function diff (oldTree, newTree) {
        let patches = {} // 存放所有元素的补丁
        let index = 0 // 第一个元素
        walk(oldTree, newTree, index, patches)  
        return patches
    }
    
    function walk (oldNode, newNode, index, patches) {
        // 每一个元素都有一个补丁
        let currentPatches = []
    
        if (!newNode) {
            currentPatches.push({type: 'REMOVE', index})
        } else if (isString(oldNode) && isString(newNode)) {
            if (oldNode !== newNode) {
                currentPatches.push({type: 'TEXT', text: newNode})
            }
        } else if (oldNode.type === newNode.type) {
            let attr = diffAttr(oldNode.props, newNode.props)
            if (Object.keys(attr).length > 0) {
                currentPatches.push({type: 'ATTR', attr})
            }

            diffChildren(oldNode.children, newNode.children, patches) // 深度优先遍历
        } else {
            current.push({type: 'REPLACE', newNode})
        }
    
        // 所有节点的补丁全部放入 patches
        // 用于后面的比较
        if (currentPatches.length) {
            patches[index] = currentPatches
        }
    }
    
    function isString (obj) {
        return typeof obj === 'string'
    }
    
    function diffAttr(oldAttrs, newAttrs) {
        let patch = {}
        for (let key in oldAttrs) {
            if (oldAttrs[key] !== newAttrs[key]) {
                patch[key] = newAttrs[key]
            }
        }
        for (let key in newAttrs) {
            if (!oldAttrs.hasOwnProperty(key)) {
                patch[key] = newAttrs[key]
            }
        }
        return patch
    }
    
    let num = 0 // 记录元素
    
    // 此处存在一个问题：就是无法检测到 新增节点
    // 可以优化的地方：节点位置互换了
    function diffChildren(oldChildren, newChildren, patches) {
        oldChildren.forEach((child, index) => {
            walk(child, newChildren[index], ++num, patches) // 注意是 ++num 
        })
    }

    return {
        diff
    }
})

